/*
 * @(#)DrawVertexConnector.java   09/09/13
 *
 * Copyright (C) 2009 Ecole des Mines d'Ales
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Contact: yulinz88@gmail.com
 *
 *
 *
 */



package fr.ema.arch3d.gea.ass;

import fr.ema.arch3d.ref.Fractal;
import fr.ema.arch3d.gea.port.MyPort;

import org.jgraph.graph.DefaultGraphCell;
import org.jgraph.graph.GraphConstants;

import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.api.Interface;
import org.objectweb.fractal.api.NoSuchInterfaceException;
import org.objectweb.fractal.api.type.InterfaceType;

import java.awt.Color;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

import java.util.Vector;

import javax.swing.BorderFactory;

/**
 * Class description
 *
 *
 * @version        1.0, 09/09/13
 * @author         Huaxi (Yulin) ZHANG
 */
public class DrawVertexConnector {

    /** Field description */
    static int pcln;

    /** Field description */
    static Vector port_client_list;

    /** Field description */
    static Vector port_control_list;

    /** Field description */
    static Vector port_server_list;

    /** Field description */
    static int psn;

    public MyVertexAss drawVertextConnector(Component component, int i) throws NoSuchInterfaceException {

        // TODO Auto-generated method stub
        String a = null;

        try {
            a = Fractal.getNameController(component).getFcName();
        } catch (NoSuchInterfaceException e) {

            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        MyVertexAss cell = createVertex(component, Color.GRAY, false,
                                        "fr.ema.ThreeDADL.julia.graph.ass.MyVertexViewConnector", i);

        // System.out.println("hhhhhhhhhhhhhh");
        return cell;
    }

    public static MyVertexAss createVertex(Component component, Color bg, boolean raised, String viewClass, int i)
            throws NoSuchInterfaceException {
        String name = Fractal.getNameController(component).getFcName();

        // name=(String) name.subSequence(0, name.length()-6);
        MyVertexAss cell = new MyVertexAss(name);

        // Fractal.getNameController(component).getFcName()+":"+
        // Fractal.getConnectorController(component).getConnector().name);
        cell.setVertexName(Fractal.getNameController(component).getFcName());
        cell.setVertexType(Fractal.getElementtypeController(component).getElementType());

        // set the view class (indirection for the renderer and the editor)
        if (viewClass != null) {
            ASCellViewFactory.setViewClass(cell.getAttributes(), viewClass);
        }

        // Set fill color
        if (bg != null) {
            GraphConstants.setGradientColor(cell.getAttributes(), bg);
            GraphConstants.setOpaque(cell.getAttributes(), true);
        }

        // Set raised border
        if (raised) {
            GraphConstants.setBorder(cell.getAttributes(), BorderFactory.createRaisedBevelBorder());
        } else {

            // Set black border
            GraphConstants.setBorderColor(cell.getAttributes(), Color.black);
        }

        // Add a Floating Port
        addPorts(cell, component);
        GraphConstants.setBounds(cell.getAttributes(), new Rectangle2D.Double(20 + i * 60, 20 + i * 60, 80, 20));

        // Set bounds

        /*
         * if(psn>pcln){
         *       GraphConstants.setBounds(cell.getAttributes(), new Rectangle2D.Double(
         *                       20, 20, pcon*20+80, psn*20+40));
         * }
         * else {
         *       GraphConstants.setBounds(cell.getAttributes(), new Rectangle2D.Double(
         *                       20, 20, pcon*20+80, pcln*20+40));
         * }
         */
        return cell;
    }

    public static DefaultGraphCell addPorts(DefaultGraphCell cell, Component component) {
        port_client_list = new Vector();
        port_server_list = new Vector();

        Interface[] client_list;
        Interface[] server_list;
        Object[]    itfs = component.getFcInterfaces();

        for (int i = 0; i < itfs.length; i++) {

            // System.out.println(((Interface)itfs[i]).getFcItfName());
            if (isClientInterface((Interface) itfs[i])) {

                // System.out.println("hereclient");
                pcln++;

                MyPort p = new MyPort();

                p.setPortName(((Interface) itfs[i]).getFcItfName());
                p.setPortType("client");
                port_client_list.add(p);
                cell.add(p);
            }

            if (!isClientInterface((Interface) itfs[i]) &&!isControlInterface((Interface) itfs[i])) {

                // System.out.println("hereserver");
                psn++;

                MyPort p = new MyPort();

                p.setPortName(((Interface) itfs[i]).getFcItfName());
                p.setPortType("server");
                port_server_list.add(p);
                cell.add(p);
            }
        }

        client_list = new Interface[pcln];
        server_list = new Interface[psn];

        for (int i = 0; i < port_client_list.size(); i++) {
            MyPort  p  = (MyPort) port_client_list.get(i);
            Point2D p2 = new Point2D.Double(GraphConstants.PERMILLE, GraphConstants.PERMILLE / (pcln + 1) * (i + 1));

            GraphConstants.setOffset(p.getAttributes(), p2);
        }

        for (int i = 0; i < port_server_list.size(); i++) {
            MyPort  p  = (MyPort) port_server_list.get(i);
            Point2D p2 = new Point2D.Double(0, GraphConstants.PERMILLE / (psn + 1) * (i + 1));

            GraphConstants.setOffset(p.getAttributes(), p2);
        }

        return cell;
    }

    /**
     * @param itf an interface
     * @return true if the interface is a  client interface
     */
    public static boolean isClientInterface(final Interface itf) {
        InterfaceType itType = (InterfaceType) itf.getFcItfType();

        return itType.isFcClientItf();
    }

    /**
     * @param itf an interface
     * @return true if itf is a control interface
     */
    public static boolean isControlInterface(final Interface itf) {
        return (itf.getFcItfName().endsWith("-controller")) || (itf.getFcItfName().equals("component"))
               || (itf.getFcItfName().equals("factory"));
    }
}
